package com.zg.common.core.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.annotation.TableField;
import com.zg.common.core.dao.autoflow.entity.SettleWorkflowInstance;
import com.zg.common.core.exception.BusinessException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.ObjectUtils;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;

/**
 * 对各种集合操作提供工具辅助
 */
public class CollectionUtils {

    /**
     * 判定一个集合是不是空的
     *
     * @param collection
     * @return
     */
    public static boolean isEmpty(Collection collection) {
        if (collection == null) {
            return true;
        }
        if (collection.isEmpty()) {
            return true;
        }
        return false;
    }

    public static boolean isEmpty(Map collection) {
        if (collection == null) {
            return true;
        }
        if (collection.isEmpty()) {
            return true;
        }
        return false;
    }


    /**
     * 获取某个字段的set 常用于获取ID的集合
     *
     * @param objects
     * @param key
     * @return
     */
    public static <T, D> Set<D> getObjectAttributeSet(Collection<T> objects, Function<? super T, ? extends D> key) {
        try {
            Set<D> set = new HashSet<>();
            if (objects == null || objects.size() == 0) {
                return set;
            }
            for (T obj : objects) {
                D value = key.apply(obj);
                if (value != null) {
                    set.add(value);
                }
            }
            return set;
        } catch (Exception e) {
            BusinessException.happen("数据的字段错误");
        }
        return Collections.emptySet();
    }


    /**
     * 获取某个字段的set 常用于获取ID的集合
     *
     * @param objects
     * @param key
     * @return
     */
    public static Set<String> getMapAttributeSet(Collection<? extends  Map> objects, String key) {
        try {
            Set<String> set = new HashSet<>();
            if (objects == null || objects.size() == 0) {
                return set;
            }
            for ( Map<?, ?> obj : objects) {
                Object value = obj.get(key);
                if (value != null) {
                    set.add(value.toString());
                }
            }
            return set;
        } catch (Exception e) {
            BusinessException.happen("数据的字段错误");
        }
        return Collections.emptySet();
    }


    /**
     * 获取某个字段的set 常用于获取ID的集合
     *
     * @param objects
     * @param key
     * @return
     */
    public static <T, D> List<D> getObjectAttributeList(Collection<T> objects, Function<? super T, ? extends D> key) {
        try {
            List<D> set = new ArrayList<>();
            if (objects == null || objects.size() == 0) {
                return set;
            }
            for (T obj : objects) {
                D value = key.apply(obj);
                if (value != null) {
                    set.add(value);
                }
            }
            return set;
        } catch (Exception e) {
            BusinessException.happen("数据的字段错误");
        }
        return Collections.emptyList();
    }

    /**
     * 把集合整理成 一个map
     *
     * @param objects  对象集合
     * @param key      键所在的字段
     * @param valuekey 值所在的字段
     * @return
     */
    public static <T, D, V> Map<D, V> collectionToMap(Collection<T> objects, Function<? super T, ? extends D> key, Function<? super T, ? extends V> valuekey) {


        Map<D, V> map = new HashMap<>();
        if (objects == null || objects.size() == 0) {
            return map;
        }
        try {
            for (T obj : objects) {
                D realkey = key.apply(obj);
                V realvalue = valuekey.apply(obj);
                if (realkey != null && realvalue != null) {
                    map.put(realkey, realvalue);
                }
            }
            return map;
        } catch (Exception e) {
            BusinessException.happen("数据的字段错误");
        }
        return map;
    }


    /**
     * 把集合整理成 一个map
     *
     * @param objects  对象集合
     * @param key      键所在的字段
     * @param valuekey 值所在的字段
     * @return
     */
    public static Map<Object, Object> collectionToMap(Collection<? extends Map> objects, String key, String valuekey) {
        Map<Object, Object> map = new HashMap<>();
        if (objects == null || objects.size() == 0) {
            return map;
        }
        try {
            for (Map obj : objects) {
                Object realkey = obj.get(key);
                Object realvalue = obj.get(valuekey);
                if (realkey != null && realvalue != null) {
                    map.put(realkey, realvalue);
                }
            }
            return map;
        } catch (Exception e) {
            BusinessException.happen("数据的字段错误");
        }
        return map;
    }

    /**
     * 把集合整理成 一个map
     *
     * @param objects 对象集合
     * @param key     键所在的字段
     * @return
     */
    public static <T extends Map> Map<String, List<T>> collectionToMap(Collection<T> objects, String key) {
        Map<String, List<T>> map = new HashMap<>();
        if (objects == null || objects.size() == 0) {
            return map;
        }
        try {
            for (T obj : objects) {
                Object realkey = obj.get(key);
                if (realkey == null) {
                    continue;
                }
                List<T> ts = map.get(realkey.toString());
                if (ts == null) {
                    ts = new ArrayList<>();
                    map.put(realkey.toString(), ts);
                }
                ts.add(obj);
            }
            return map;
        } catch (Exception e) {
            BusinessException.happen("数据的字段错误");
        }
        return map;
    }

    /**
     * 把集合整理成 一个map
     *
     * @param objects 对象集合
     * @param key     键所在的字段
     * @return
     */
    public static <T, R> Map<R, T> collectionToMap(Collection<T> objects, Function<? super T, ? extends R> key) {


        Map<R, T> map = new HashMap<>();
        if (objects == null || objects.size() == 0) {
            return map;
        }
        try {
            for (T obj : objects) {
                R realkey = key.apply(obj);
                map.put(realkey, obj);
            }
            return map;
        } catch (Exception e) {
            BusinessException.happen("数据的字段错误");
        }
        return map;
    }

    /**
     * 转化基础的字典数据
     *
     * @param list
     * @return
     */
    public static Map<Object, Object> tansBaseDict(List<Map<String, Object>> list) {
        return collectionToMap(list, "value", "name");
    }


    /**
     * 通过一个字段 给对象分组
     *
     * @param objects
     * @param key
     * @param <T>
     * @param <R>
     * @return
     */
    public static <T, R> Map<R, List<T>> groupByFiled(Collection<T> objects, Function<? super T, ? extends R> key) {


        Map<R, List<T>> map = new HashMap<>();
        if (objects == null || objects.size() == 0) {
            return map;
        }
        try {
            for (T obj : objects) {
                R realkey = key.apply(obj);
                List<T> ts = map.get(realkey);
                if (ts == null) {
                    ts = new ArrayList<>();
                    map.put(realkey, ts);
                }
                ts.add(obj);
            }
            return map;
        } catch (Exception e) {
            BusinessException.happen("数据的字段错误");
        }
        return map;
    }


    /**
     * 用特定字符串拼接字符串队列
     *
     * @param valuesList
     * @param s
     * @return
     */
    public static String ListToStringStr(List<String> valuesList, String s) {
        if (valuesList == null || valuesList.size() == 0) {
            return "";
        }
        StringBuffer reStr = new StringBuffer();
        reStr.append(valuesList.get(0));
        for (int i = 1; i < valuesList.size(); ++i) {
            reStr.append(s);
            reStr.append(valuesList.get(i));
        }
        return reStr.toString();
    }

    /**
     * 用特定字符串拼接字符串队列
     */
    public static <T> String ListToStringStr(List<T> valuesList, Function<? super T, ? extends Object> key, String s) {
        if (valuesList == null || valuesList.size() == 0) {
            return "";
        }
        StringBuffer reStr = new StringBuffer();
        T obj1 = valuesList.get(0);
        reStr.append(key.apply(obj1).toString());
        for (int i = 1; i < valuesList.size(); ++i) {
            reStr.append(s);
            T obj = valuesList.get(i);
            Object apply = key.apply(obj);
            reStr.append(apply.toString());
        }
        return reStr.toString();
    }

    public static <T> List<T> findIn(Collection<T> valuesList, Function<? super T, ? extends Object> key, Object value) {
        ArrayList<T> ts = new ArrayList<>();
        for (T t : valuesList) {
            Object apply = key.apply(t);
            if (ObjectUtils.nullSafeEquals(apply, value)) {
                ts.add(t);
            }
        }
        return ts;
    }


    public static String getObjectValue(Object obj, String key) {
        try {
            key = key.toLowerCase(Locale.ROOT);
            Field declaredField = obj.getClass().getDeclaredField(key);
            declaredField.setAccessible(true);
            Object o = declaredField.get(obj);
            if (o == null) {
                return "";
            }
            return o.toString();
        } catch (Exception e) {
            return "";
        }
    }

    public static void setObjectValue(Object obj, String key, String value) {
        try {
            Field declaredField = obj.getClass().getDeclaredField(key);
            declaredField.setAccessible(true);
            declaredField.set(obj, value);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    //横向结构的表 转对象
    public static <T> List<T> hengBiaoToObjList(JSONObject htjjdzb, Class<T> tClass) {

        List<T> list = new ArrayList<>();
        Set<String> keySet = htjjdzb.keySet();

        try {
            while (true) {
                T t = tClass.getDeclaredConstructor().newInstance();
                int nullnum = 0;
                for (String k : keySet) {
                    JSONArray jsonArray = htjjdzb.getJSONArray(k);
                    String remove = "";
                    if (jsonArray.size() > 0) {
                        Object remove1 = jsonArray.remove(0);
                        if(remove1!=null)
                        {
                            remove = remove1.toString();
                        }
                    } else {
                        nullnum++;
                    }
                    k = k.toLowerCase(Locale.ROOT);
                    setObjectValue(t, k, remove);
                }
                if (nullnum == keySet.size()) {
                    break;
                }

                list.add(t);
            }

        } catch (Exception e) {
            BusinessException.happen("服务器异常");
        }
        return list;

    }


    //向流程中存入保留字段信息
    public static void checkAndSaveDefColumn(JSONObject data, SettleWorkflowInstance ins) {
        //向流程中存入保留字段信息
        if (data == null) {
            return;
        }
        //所有的字段
        Field[] declaredFields = SettleWorkflowInstance.class.getDeclaredFields();
        Map<String,Field> declaredFieldsmap = new HashMap<>();
        for (Field field:declaredFields  ) {
            TableField annotation = field.getAnnotation(TableField.class);
            if(annotation!=null)
            {
                String value = annotation.value();
                declaredFieldsmap.put(value,field);
            }
        }
        String[] strings = data.keySet().toArray(new String[ data.keySet().size()]);
        for (String key:strings) {

            Field field = declaredFieldsmap.get(key);
            if(field ==null)
            {
                data.remove(key);
                System.out.println("固有字段错误" + key);
                continue;
//                throw new InfoException("固有字段错误" + key);
            }
            Object value = data.get(key);
            if(value==null){
                continue;
            }

            String str = value.toString();

            try {
                if(StringUtils.isBlank(str))
                {
                    value =null;
                }
                else  if( field.getType() == Integer.class)
                {
                    value = Integer.parseInt(str);
                }else  if( field.getType() == Long.class)
                {
                    value = Long.parseLong(str);
                }else  if( field.getType() == BigDecimal.class)
                {
                    value = new BigDecimal(str);
                }
                else  if( field.getType() == String.class)
                {
                    value = str;
                }
                else{
                    data.remove(key);
                    System.out.println("固有字段格式错误" + key+":"+value);
                    continue;
                }

            }catch (Exception e)
            {
                data.remove(key);
                System.out.println("固有字段格式错误" + key+":"+value);
                continue;
            }
            field.setAccessible(true);
            try {
                field.set(ins,value);
            }catch (Exception e)
            {
//                throw new InfoException("固有字段格式错误" + key+":"+value);
                data.remove(key);
                System.out.println("固有字段格式错误" + key+":"+value);
            }
        }

    }

    /**
     * 数组转list
     * @param ts
     * @param <T>
     * @return
     */
    public static <T> List<T>  arrayToList(T[] ts)
    {
        ArrayList<T> ts1 = new ArrayList<>();
        if(ts==null  || ts.length == 0)
        {
            return ts1;
        }
        for (T t :ts  ) {
            ts1.add(t);
        }
        return  ts1;
    }


    /**
     * MAP数字 通过id数组排序 常见的场景就是通过idlist 取数据是乱序的 然后重新排序
     * @param datalist
     * @param idlist
     * @param KEY
     * @return
     */
    public static List<Map> listSortByIdList(List<Map> datalist, List<String> idlist, String KEY) {
        Map<String, List<Map>> stringListMap = collectionToMap(datalist, KEY);
        List<Map> newlist = new ArrayList<>();
        for (String id:idlist  ) {
            List<Map> list = stringListMap.get(id);
            if(!ObjectUtils.isEmpty(list)){
                newlist.addAll(list);
            }
        }
        return  newlist;
    }





    /**
     * MAP数字 通过id数组排序 常见的场景就是通过idlist 取数据是乱序的 然后重新排序
     * @param datalist
     * @param idlist
     * @param key
     * @return
     */
    public static <T> List<T> listSortByIdList(List<T> datalist, List<String> idlist,  Function<? super T, String> key) {

        Map<String, T> stringListMap = collectionToMap(datalist, key);
        List<T> newlist = new ArrayList<>();
        for (String id:idlist  ) {
            T t = stringListMap.get(id);
            if(t!=null){
                newlist.add(t);
            }
        }
        return  newlist;
    }

    /**
     * json数组字符串转java对象
     * @param hget
     * @param tClass
     * @param <T>
     * @return
     */
    public static <T> List<T> JsonStringToList(Object hget, Class<T> tClass) {
        if(hget==null || "".equals(hget))
        {
            return  new ArrayList<>();
        }

        JSONArray array = JSON.parseArray(hget.toString());
        List<T> list = array.toJavaList(tClass);
        return  list;
    }
}
